package com.vcvt.officewriter.controller;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Controller
@RequestMapping("/")
public class IndexController {

    private static final Pattern PATTERN = Pattern.compile("\\$\\{(.+?)}", Pattern.CASE_INSENSITIVE);

    @Value("${templatePath}")
    private String templatePath;

    public static void writer(String inputSrc, String outSrc, Map<String, String> param) {
        try {
            XWPFDocument doc = new XWPFDocument(POIXMLDocument.openPackage(inputSrc));
            for (XWPFParagraph p : doc.getParagraphs()) {
                List<XWPFRun> runs = p.getRuns();
                if (runs != null) {
                    for (XWPFRun run : runs) {
                        //需要替换的文本
                        String text = run.getText(0);
                        //替换指定的文本
                        if (text != null) {
                            boolean isSetText = false;
                            for (Map.Entry<String, String> entry : param.entrySet()) {
                                String key = entry.getKey();
                                // 在配置文件中有这个关键字对应的键
                                if (text.contains(key)) {
                                    isSetText = true;
                                    Object value = entry.getValue();
                                    if (value != null) {
                                        if (text.contains(key)) {
                                            text = text.replace(key, value.toString());
                                        }
                                    }
                                }
                            }
                            if (isSetText) {
                                run.setText(text, 0);
                            }
                        }
                    }
                }
            }
            for (XWPFTable tab : doc.getTables()) {
                for (XWPFTableRow row : tab.getRows()) {
                    for (XWPFTableCell cell : row.getTableCells()) {
                        //注意，getParagraphs一定不能漏掉
                        //因为一个表格里面可能会有多个需要替换的文字
                        //如果没有这个步骤那么文字会替换不了
                        for (XWPFParagraph p : cell.getParagraphs()) {
                            for (XWPFRun r : p.getRuns()) {
                                String text = r.getText(0);
                                if (text != null) {
                                    for (String key : param.keySet()) {
                                        if (text.equals(key)) {
                                            r.setText(param.get(text), 0);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            doc.write(new FileOutputStream(outSrc));
            System.out.println("替换完成: " + inputSrc + ", 目标文件路径: " + outSrc);
        } catch (IOException e) {
            System.err.println("替换失败: " + inputSrc);
            e.printStackTrace();
        }
    }

    public static void replaceExcel(String inPath, String outPath, Map<String, String> params) {
        try (InputStream is = new FileInputStream(new File(inPath));
             OutputStream out = new FileOutputStream(new File(outPath))) {
            Workbook wb = WorkbookFactory.create(is);
            // 获取Excel的工作表sheet，下标从0开始。
            Sheet sheet = wb.getSheetAt(0);
            // 获取Excel的行数
            int trLength = sheet.getLastRowNum();
            for (int i = 0; i < trLength; i++) {
                // 获取Excel的行，下标从0开始
                Row row = sheet.getRow(i);
                // 若行为空，则遍历下一行
                if (row == null) {
                    continue;
                }
                int minColIx = row.getFirstCellNum();
                int maxColIx = row.getLastCellNum();
                for (int colIx = minColIx; colIx < maxColIx; colIx++) {
                    // 获取指定单元格，单元格从左到右下标从0开始
                    Cell cell = row.getCell(colIx);
                    if (cell == null || cell.getCellTypeEnum() != CellType.STRING) {
                        continue;
                    }
                    String runText = cell.getStringCellValue();
                    if ("".equals(runText)) {
                        continue;
                    }
                    Matcher matcher = PATTERN.matcher(runText);
                    if (matcher.find()) {
                        while ((matcher = PATTERN.matcher(runText)).find()) {
                            runText = matcher.replaceFirst(String.valueOf(params.get(matcher.group(0))));
                        }
                        cell.setCellValue(runText);
                    }
                }
            }
            wb.write(out);
            System.out.println("替换完成: " + inPath + ", 目标文件路径: " + outPath);
        } catch (Exception e) {
            System.err.println("替换失败: " + inPath);
            e.printStackTrace();
        }
    }

    @RequestMapping
    public String index() {
        return "index.html";
    }

    @PostMapping("/replace")
    public void replace(@RequestParam Map<String, String> params, HttpServletResponse response) throws IOException{
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html; charset=utf-8");
        PrintWriter out=response.getWriter();
        Map<String, String> replaceMap = new HashMap<>();
        for (String key : params.keySet()) {
            Optional<String> opt = Optional.ofNullable(key);
            if (opt.isPresent()) {
                replaceMap.put(key, params.get(key));
            } else {
                System.out.println(key + "对应的值为空");
            }
        }
        String targetPath = templatePath + "\\新";
        File dirPath = new File(templatePath);
        if (dirPath.isDirectory()) {
            File[] fileList = dirPath.listFiles();
            File targetFile = new File(targetPath);
            if (!targetFile.exists()) {
                boolean succeed = targetFile.mkdir();
                if (!succeed) {
                    out.print("<script>alert('创建"+targetPath+"失败');history.go(-1);</script>");
                    return;
                }
            }
            assert fileList != null;
            for (File file : fileList) {
                String srcPath = file.getPath();
                String destPath = targetPath + "\\" + file.getName();
                if (file.getName().endsWith("docx")) {
                    writer(srcPath, destPath, replaceMap);
                } else if (file.getName().endsWith(".xls") || file.getName().endsWith(".xlsx")) {
                    replaceExcel(srcPath, destPath, replaceMap);
                } else {
                    if (file.isFile()) {
                        System.out.println(file.getName() + "格式不满足要求, 文件格式必须为docx、xls、xlsx");
                    }
                }
            }
        } else {
            out.print("<script>alert('模板目录不存在');history.go(-1);</script>");
            return;
        }
        out.print("<script>alert('替换成功');history.go(-1);</script>");
    }
}
